package com.sharelords.biz.join;

import com.sharelords.biz.common.BaseBizImpl;
import com.sharelords.biz.util.BizQueryUtil;
import com.sharelords.biz.util.BizQueryUtil.Impl;
import com.sharelords.biz.util.InvokeUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author 千古龙少
 * @Description: 文件内容组装
 * @date 2019年9月8日 下午9:54:25
 */
@Service
public class FileContentJoin {

    private String fileContent;

    private static final String IMPL = "Impl";
    private static final String PACKAGE_IMPL = ".impl";
    private static final String LINE_FEED = "\r\n";

    /**
     * 包名
     */
    private static final String PACKAGE_NAME = "package {0};" + LINE_FEED;
    /**
     * 引用
     */
    private static final String IMPORT = "import {0};" + LINE_FEED;
    /**
     * 注解
     */
    private static final String ANNOTATION = "@{0}" + LINE_FEED;
    /**
     * 注入
     */
    private static final String AUTOWIRED = "@Autowired" + LINE_FEED + "private {0} mapper;" + LINE_FEED;
    /**
     * 文件框架
     */
    private static final String FILE_STRUCTURE = "public class {0} extends BaseBizImpl<{1}> implements {2} '{'" + LINE_FEED + "{3}" + LINE_FEED + "{4}" + LINE_FEED + "'}'";

    /**
     * 接口class对象
     */
    private Class<?> clazz;
    /**
     * 包路径
     */
    private String packageName;
    /**
     * 父类名
     */
    private String className;

    /**
     * 当前实现类类名
     */
    private String implClassName;
    /**
     * 包名
     */
    private String implPackage;
    /**
     * 引用
     */
    private String imports;
    /**
     * 注解
     */
    private String annotations;
    /**
     * 泛型，逗号分隔
     */
    private String generics;
    /**
     * 泛型，逗号分隔
     */
    private String autowiredStr;
    /**
     * 方法
     */
    private String methods = "";

    public FileContentJoin(Class<?> clazz) {
        this.clazz = clazz;
        this.packageName = clazz.getPackage().getName();
        this.className = clazz.getSimpleName();
        this.init();
    }

    public String getImplClassName() {
        return implClassName;
    }

    /**
     * @Description: 初始化
     * @author 千古龙少
     * @date 2019年9月8日 下午10:04:45
     */
    private void init() {
        this.implPackage = MessageFormat.format(PACKAGE_NAME, this.packageName + PACKAGE_IMPL);
        this.implClassName = this.className + IMPL;
        this.annotations = this.anoNames(Service.class);
    }

    /**
     * @return
     * @Description: 类注解组装
     * @author 千古龙少
     * @date 2019年9月8日 下午10:04:58
     */
    private String anoNames(Class<?>... classes) {
        if (classes == null || classes.length == 0) {
            return "";
        }

        StringBuffer buffer = new StringBuffer();
        for (Class<?> clazz : classes) {
            buffer.append(MessageFormat.format(ANNOTATION, clazz.getSimpleName()));
        }

        return buffer.toString();
    }

    /**
     * @param classes
     * @return
     * @Description: 泛型组装
     * @author 千古龙少
     * @date 2019年9月15日 下午2:35:16
     */
    public FileContentJoin generics(Class<?>... classes) {
        if (classes == null || classes.length == 0) {
            return this;
        }

        List<String> list = new ArrayList<>();
        for (Class<?> aClass : classes) {
            list.add(aClass.getSimpleName());
        }

        this.generics = StringUtils.join(list, ",");
        return this;
    }

    /**
     * @param mapperClass
     * @return
     * @Description: mapper注入元素组装
     * @author 千古龙少
     * @date 2019年9月15日 下午2:35:16
     */
    public FileContentJoin autowired(Class<?> mapperClass) {
        if (mapperClass == null) {
            return this;
        }

        this.autowiredStr = MessageFormat.format(AUTOWIRED, mapperClass.getSimpleName());
        return this;
    }

    /**
     * @param classes
     * @return
     * @Description: 引用class路径名称组装
     * @author 千古龙少
     * @date 2019年9月8日 下午10:04:58
     */
    public FileContentJoin imports(Class<?>... classes) {
        if (classes == null || classes.length == 0) {
            return this;
        }

        List<Class<?>> importList = InvokeUtil.toList(classes);
        importList.add(Collections.class);
        importList.add(List.class);
        importList.add(Service.class);
        importList.add(Autowired.class);
        importList.add(BaseBizImpl.class);
        importList.add(BizQueryUtil.class);
        importList.add(Impl.class);
        importList.add(this.clazz);

        StringBuilder builder = new StringBuilder();
        for (Class<?> aClass : importList) {
            String classPath = aClass.getCanonicalName();
            if (classPath.startsWith("java.lang.")) {
                continue;
            }

            builder.append(MessageFormat.format(IMPORT, classPath));
        }

        this.imports = builder.toString();

        return this;
    }

    /**
     * @param clazz
     * @param boClass
     * @return
     * @Description: 方法组装
     * @author 千古龙少
     * @date 2019年9月8日 下午10:07:07
     */
    public <Bo> FileContentJoin methods(Class<?> clazz, Class<Bo> boClass) {
        MethodJoin<Bo> methodJoin = new MethodJoin<>(clazz, boClass);

        // 方法体
        List<String> methodList = methodJoin.getMethods();
        if (methodList != null && !methodList.isEmpty()) {
            this.methods = StringUtils.join(methodList, LINE_FEED);
        }

        // 引用类型
        List<Class<?>> importList = methodJoin.getImports();
        if (importList != null && !importList.isEmpty()) {
            StringBuilder builder = new StringBuilder();
            for (Class<?> importClazz : importList) {
                builder.append(MessageFormat.format(IMPORT, importClazz.getCanonicalName()));
            }
            this.imports += builder.toString();
        }

        return this;
    }

    /**
     * @Description: 结果组装
     * @author 千古龙少
     * @date 2019年9月15日 下午2:56:25
     */
    private void groupResult() {
        StringBuilder builder = new StringBuilder();
        builder.append(implPackage).append(LINE_FEED)
                .append(imports).append(LINE_FEED)
                .append(annotations);

        // class组装
        String mainContent = MessageFormat.format(FILE_STRUCTURE, implClassName, generics, className, autowiredStr, methods);
        builder.append(mainContent);

        this.fileContent = builder.toString();
    }

    /**
     * @return String
     * @Description: 获取结果
     * @author 千古龙少
     * @date 2019年9月8日 下午10:11:11
     */
    public String getResult() {
        this.groupResult();
        return this.fileContent;
    }

}
